import axios, { type InternalAxiosRequestConfig, type AxiosResponse } from "axios";
import qs from "qs";
import { useUserStoreHook } from "@/store/modules/user.store";
import { ResultEnum } from "@/enums/api/result.enum";
import { Auth } from "@/utils/auth";
import router from "@/router";

// 创建 axios 实例
const service = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API,
  timeout: 50000,
  headers: { "Content-Type": "application/json;charset=utf-8" },
  paramsSerializer: (params) => qs.stringify(params),
});

// 请求拦截器
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    console.log(
      "[",
      config.method,
      "]",
      config.url,
      config.method === "get" ? "params:" : "data:",
      config.method === "get" ? config.params : config.data
    );
    const accessToken = Auth.getAccessToken();
    // 如果 Authorization 设置为 no-auth，则不携带 Token
    if (config.headers.Authorization !== "no-auth" && accessToken) {
      config.headers.Authorization = `Bearer ${accessToken}`;
    } else {
      delete config.headers.Authorization;
    }
    return config;
  },
  (error) => Promise.reject(error)
);
// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse) => {
    console.log(
      "[",
      response.config.method,
      "]",
      response.config.url,
      response.config.method === "get" ? "params:" : "data:",
      response.config.method === "get" ? response.config.params : response.config.data,
      "response",
      response
    );
    // 如果响应是二进制流，则直接返回，用于下载文件、Excel 导出等
    if (response.config.responseType === "blob") {
      return response;
    }
    if (
      response.headers["content-type"]?.includes("application/octet-stream")
      // response.headers["content-type"]?.includes("text/plain; charset=gb2312")
    ) {
      // 如果是 octet 响应,直接返回
      console.warn("文件请求响应，直接返回，后续按需处理");
      return response;
    }
    if (response.data.code === ResultEnum.SUCCESS) {
      return response.data.data;
    }
    // hmi 接口返回的数据，没有 code 字段，直接返回数据
    return response.data;
    // const { code, data, msg } = response.data;
    // if (code === ResultEnum.SUCCESS) {
    //   return data;
    // }
    // ElMessage.error(msg || "系统出错");
    // return Promise.reject(new Error(msg || "Error"));
  },
  async (error) => {
    console.error("request error", error); // for debug
    const { config, response } = error;
    if (response) {
      const { code, msg } = response.data;
      if (code === ResultEnum.ACCESS_TOKEN_INVALID) {
        // Token 过期，刷新 Token
        return handleTokenRefresh(config);
      } else if (code === ResultEnum.REFRESH_TOKEN_INVALID) {
        // 刷新 Token 过期，跳转登录页
        await handleSessionExpired();
        return Promise.reject(new Error(msg || "Error"));
      } else {
        ElMessage.error(msg || response.config.url + " " + error.message || "系统出错");
      }
    }
    return Promise.reject(error.message);
  }
);
export default service;
// 是否正在刷新标识，避免重复刷新
let isRefreshing = false;
// 因 Token 过期导致的请求等待队列
const waitingQueue: Array<() => void> = [];
// 刷新 Token 处理
async function handleTokenRefresh(config: InternalAxiosRequestConfig) {
  return new Promise((resolve) => {
    // 封装需要重试的请求
    const retryRequest = () => {
      config.headers.Authorization = `Bearer ${Auth.getAccessToken()}`;
      resolve(service(config));
    };
    waitingQueue.push(retryRequest);
    if (!isRefreshing) {
      isRefreshing = true;
      useUserStoreHook()
        .refreshToken()
        .then(() => {
          // 依次重试队列中所有请求, 重试后清空队列
          waitingQueue.forEach((callback) => callback());
          waitingQueue.length = 0;
        })
        .catch(async (error) => {
          console.error("handleTokenRefresh error", error);
          // 刷新 Token 失败，跳转登录页
          await handleSessionExpired();
        })
        .finally(() => {
          isRefreshing = false;
        });
    }
  });
}
// 处理会话过期
async function handleSessionExpired() {
  ElNotification({
    title: "提示",
    message: "您的会话已过期，请重新登录",
    type: "info",
  });
  await useUserStoreHook().resetAllState();
  router.push("/login");
}

/** 导出一个实现方法 parseBlobToJson  */
/**
 * 将Blob数据解析为JSON对象
 * @param blob - 要解析的Blob数据
 * @returns Promise<any> - 解析后的JSON对象
 */
export const parseBlobToJson = (blob: Blob): Promise<any> => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    reader.onload = () => {
      try {
        // 将文本解析为JSON对象
        const jsonContent = JSON.parse(reader.result as string);
        // console.log("成功获取配置内容:", jsonContent);
        resolve(jsonContent);
      } catch (parseError) {
        console.error("JSON解析错误:", parseError);
        reject(parseError);
      }
    };

    reader.onerror = () => {
      console.error("文件读取错误");
      reject(new Error("文件读取错误"));
    };

    // 开始读取blob为文本
    reader.readAsText(blob);
  });
};
